; loader.asm - 16位实模式，加载GDT，进入保护模式，设置分页，跳转高地址内核
org 0x9000

%include "gdt.asm"

section .text
start:
    cli
    xor ax, ax
    mov ds, ax
    mov es, ax
    mov ss, ax
    mov sp, 0x7C00

    ; 打开A20
    in al, 0x92
    or al, 2
    out 0x92, al

    ; 加载GDT
    lgdt [gdt_desc]

    ; 设置PE位，进入保护模式
    mov eax, cr0
    or eax, 1
    mov cr0, eax

    ; 远跳转保护模式CS
    jmp 0x08:protected_mode_start

bits 32
protected_mode_start:
    mov ax, 0x10
    mov ds, ax
    mov es, ax
    mov ss, ax
    mov fs, ax
    mov gs, ax

    ; 清空direction flag
    cld

    ; ===== 分页结构初始化 =====
    mov edi, 0x10000         ; 页目录物理地址
    mov ecx, 1024*5          ; 1目录+4页表
    xor eax, eax
    rep stosd                ; 清零

    ; 页目录设置
    mov edi, 0x10000
    mov eax, 0x11003         ; 页表物理地址=0x11000 | P|RW
    mov [edi], eax           ; 第0项（0x0~0x3FFFFF）
    mov [edi+768*4], eax     ; 第768项（0xC0000000~0xC03FFFFF）

    ; 页表设置
    mov esi, 0x11000
    mov ecx, 1024
    mov ebx, 0
.set_page_table:
    mov eax, ebx
    or eax, 0x3
    mov [esi], eax
    add esi, 4
    add ebx, 0x1000
    loop .set_page_table

    ; 加载CR3
    mov eax, 0x10000
    mov cr3, eax

    ; 打开分页
    mov eax, cr0
    or eax, 0x80000000
    mov cr0, eax

    ; 跳转到高地址内核入口 0xC0010000（映射物理0x10000, 方便测试）
    jmp 0x08:0xC0010000

hang:
    jmp hang